package com.tlgen.coopera.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.tlgen.coopera.factory.ConfigLocalFactory;
import com.tlgen.coopera.factory.RegistryLocalFactory;
import com.tlgen.coopera.model.ConfigData;
import com.tlgen.coopera.model.RegistryServer;
import com.tlgen.coopera.service.ConfigService;
import okhttp3.*;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.tlgen.coopera.utils.HttpUtils.selectLocalIp;

@Service
public class ConfigServiceImpl implements ConfigService {

    @Override
    public void notifyAllInstance() {
        List<RegistryServer> registryList = RegistryLocalFactory.getInstance().getRegistryList();
        for (RegistryServer registryServer : registryList) {
            ConfigData configData = ConfigLocalFactory.getInstance().getConfigData();
            // 向其他节点发送需要同步的数据
            if (!Objects.equals(selectLocalIp(), registryServer.getIp())) {
                String url = "http://" + registryServer.getIp() + ":" + registryServer.getPort() + "/config/receive";
                Call call = new OkHttpClient().newBuilder()
                        .connectTimeout(3, TimeUnit.SECONDS)
                        .readTimeout(3, TimeUnit.SECONDS)
                        .writeTimeout(3, TimeUnit.SECONDS)
                        .build().newCall(new Request.Builder()
                                .url(url)
                                .post(RequestBody.create(
                                        MediaType.parse("application/json; charset=utf-8"),
                                        JSONObject.toJSONString(configData)))
                                .build());
                // 返回请求结果
                try {
                    Response response = call.execute();
                    assert response.body() != null;
                    System.out.println(response.body().string());
                } catch (IOException e) {
                    System.out.println(url + " 调用失败");
                }
            }
        }
    }

    @Override
    public void pullAllInstance() {
        List<ConfigData> configList = new ArrayList<>();
        List<RegistryServer> registryList = RegistryLocalFactory.getInstance().getRegistryList();
        for (RegistryServer registryServer : registryList) {
            // 向其他节点发送需要同步的数据
            if (!Objects.equals(selectLocalIp(), registryServer.getIp())) {
                String url = "http://" + registryServer.getIp() + ":" + registryServer.getPort() + "/config/select";
                Call call = new OkHttpClient().newBuilder()
                        .connectTimeout(3, TimeUnit.SECONDS)
                        .readTimeout(3, TimeUnit.SECONDS)
                        .writeTimeout(3, TimeUnit.SECONDS)
                        .build().newCall(new Request.Builder()
                                .url(url)
                                .get()
                                .build());
                // 返回请求结果
                try {
                    Response response = call.execute();
                    assert response.body() != null;
                    JSONObject jsonObject = JSONObject.parseObject(response.body().string());
                    JSONObject data = (JSONObject) jsonObject.get("data");
                    ConfigData configData = new ConfigData();
                    configData.setVersion((Long) data.get("version"));
                    configData.setContent(data.get("content"));
                    configList.add(configData);
                } catch (IOException e) {
                    System.out.println(url + " 调用失败");
                }
            }
        }
        System.out.println("已拉取全量配置");
        System.out.println(configList);
        ConfigData configData = configList.stream().max(Comparator.comparing(ConfigData::getVersion)).orElse(null);
        Optional.ofNullable(configData).ifPresent(x -> saveToLocalInstance(configData));
    }


    @Override
    public void saveToLocalInstance(ConfigData receiveConfigData) {
        ConfigLocalFactory.getInstance().setConfigData(receiveConfigData);
    }

    @Override
    public void updateToLocalInstance(ConfigData receiveConfigData) {
        saveToLocalInstance(receiveConfigData);
        notifyAllInstance();
    }

}
